package com.panfeng.xcloud.scheduler.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.binance.client.model.enums.CandlestickInterval;
import com.panfeng.xcloud.boss.provider.dto.request.*;
import com.panfeng.xcloud.boss.provider.rpc.assets.AssetsBasicInfoFeignApi;
import com.panfeng.xcloud.boss.provider.rpc.assets.ExchangeOperateServiceFeignApi;
import com.panfeng.xcloud.boss.provider.rpc.assets.ExecuteOrderServiceFeignApi;
import com.panfeng.xcloud.boss.provider.rpc.member.MemberBasicInfoFeignApi;
import com.panfeng.xcloud.boss.provider.rpc.member.UserInfoFeignApi;
import com.panfeng.xcloud.common.core.configuration.DataDictionaryConfig;
import com.panfeng.xcloud.common.core.web.vo.*;
import com.panfeng.xcloud.scheduler.service.IFeignService;
import groovy.util.logging.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.LinkedHashMap;

@Slf4j
@Service
public class FeignServiceImpl implements IFeignService {

    private static Logger log = LoggerFactory.getLogger(FeignServiceImpl.class);

    @Autowired
    private UserInfoFeignApi userInfoFeignApi;

    @Autowired
    private AssetsBasicInfoFeignApi assetsBasicInfoFeignApi;

    @Autowired
    private MemberBasicInfoFeignApi memberBasicInfoFeignApi;

    @Autowired
    private ExecuteOrderServiceFeignApi executeOrderServiceFeignApi;

    @Autowired
    private ExchangeOperateServiceFeignApi exchangeOperateServiceFeignApi;

    @Autowired
    private DataDictionaryConfig config;

    @Override
    @Async("asyncExecutor")
    public void sendEmail(String message) {
        userInfoFeignApi.sendEmail(new SendEmailReqDTO("超级量化正式版-" + message));
    }

    @Override
    @Async("asyncExecutor")
    public void syncAssetsDataDictionary() {
        SyncBasicInfoReqDTO syncBasicInfoReqDTO = new SyncBasicInfoReqDTO();
        syncBasicInfoReqDTO.setCodeToNameMap(config.getCodeToNameMap());
        assetsBasicInfoFeignApi.syncBasicInfo(syncBasicInfoReqDTO);
    }

    @Override
    @Async("asyncExecutor")
    public void syncMemberDataDictionary() {
        SyncBasicInfoReqDTO syncBasicInfoReqDTO = new SyncBasicInfoReqDTO();
        syncBasicInfoReqDTO.setCodeToNameMap(config.getCodeToNameMap());
        memberBasicInfoFeignApi.syncBasicInfo(syncBasicInfoReqDTO);
    }

    @Override
    public TradeResponseVO chooseSendOrderHttp(OperateBotReqDTO operateBotReqDTO, Integer systemInnerType) throws Exception {
        ResponseVO responseVO = executeOrderServiceFeignApi.chooseSendOrderHttp(operateBotReqDTO, systemInnerType);
        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), TradeResponseVO.class);
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public BigDecimal toSetOpenOrderAmount(OperateBotReqDTO operateBotReqDTO, BigDecimal amount) throws Exception {
        ResponseVO responseVO = executeOrderServiceFeignApi.toSetOpenOrderAmount(operateBotReqDTO, amount);
        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return new BigDecimal(String.valueOf(responseVO.getData()));
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public BigDecimal getTotalAvaliableMoney(Integer exchangeType, String userId, String valuationAsset) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        OperateBotReqDTO operateBotReqDTO = new OperateBotReqDTO();
        operateBotReqDTO.setExchangeType(exchangeType);
        operateBotReqDTO.setUserId(userId);

        exchangeOperateReqDTO.setValuationAsset(valuationAsset);
        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getTotalAvaliableMoney(exchangeOperateReqDTO);
        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return new BigDecimal((String) responseVO.getData());
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public BigDecimal getRiskRate(Integer exchangeType, String userId, String contractCode, String direction) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        OperateBotReqDTO operateBotReqDTO = new OperateBotReqDTO();
        operateBotReqDTO.setExchangeType(exchangeType);
        operateBotReqDTO.setUserId(userId);
        operateBotReqDTO.setDirection(direction);
        exchangeOperateReqDTO.setContractCode(contractCode);
        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getRiskRate(exchangeOperateReqDTO);
        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return ((String) responseVO.getData()).equals("null") ? null : new BigDecimal((String) responseVO.getData());
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public BigDecimal getAvaliablePosition(Integer exchangeType, String userId, String contractCode, String direction, Integer leverRate) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        OperateBotReqDTO operateBotReqDTO = new OperateBotReqDTO();
        operateBotReqDTO.setExchangeType(exchangeType);
        operateBotReqDTO.setUserId(userId);
        operateBotReqDTO.setDirection(direction);
        operateBotReqDTO.setLeverRate(leverRate);

        exchangeOperateReqDTO.setContractCode(contractCode);
        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getAvaliablePosition(exchangeOperateReqDTO);

        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return new BigDecimal((String) responseVO.getData());
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public BigDecimal getAvaliableMoney(Integer exchangeType, String userId, String contractCode) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        OperateBotReqDTO operateBotReqDTO = new OperateBotReqDTO();
        operateBotReqDTO.setExchangeType(exchangeType);
        operateBotReqDTO.setUserId(userId);

        exchangeOperateReqDTO.setContractCode(contractCode);
        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getAvaliableMoney(exchangeOperateReqDTO);
        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return new BigDecimal((String) responseVO.getData());
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public BigDecimal getAvaliablePieces(Integer exchangeType, OperateBotReqDTO operateBotReqDTO) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getAvaliablePieces(exchangeOperateReqDTO);
        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return new BigDecimal((String) responseVO.getData());
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public TradeResponseVO trade(Integer exchangeType, OperateBotReqDTO operateBotReqDTO, QuantBotDetailDTO quantBotDetailDTO) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);
        exchangeOperateReqDTO.setQuantBotDetailDTO(quantBotDetailDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.trade(exchangeOperateReqDTO);

        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), TradeResponseVO.class);
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public OrderDetailResponseVO getOrderDetail(Integer exchangeType, OperateBotReqDTO operateBotReqDTO, TradeResponseVO tradeResponseVO) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);
        exchangeOperateReqDTO.setTradeResponseVO(tradeResponseVO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getOrderDetail(exchangeOperateReqDTO);

        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), OrderDetailResponseVO.class);
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public String transferInner(InnerTransferVO innerTransferVO) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        exchangeOperateReqDTO.setInnerTransferVO(innerTransferVO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.transferInner(exchangeOperateReqDTO);
        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return (String) responseVO.getData();
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public BigDecimal getAppearMarketPrice(Integer exchangeType, String userId, String destinationCoin, String sourceCoin) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        OperateBotReqDTO operateBotReqDTO = new OperateBotReqDTO();
        operateBotReqDTO.setExchangeType(exchangeType);
        operateBotReqDTO.setDestinationCoin(destinationCoin);
        operateBotReqDTO.setSourceCoin(sourceCoin);
        operateBotReqDTO.setUserId(userId);

        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getAppearMarketPrice(exchangeOperateReqDTO);

        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return new BigDecimal((String) responseVO.getData());
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public JSONObject getMarketPriceDepth(Integer exchangeType, String userId, String destinationCoin, String sourceCoin) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        OperateBotReqDTO operateBotReqDTO = new OperateBotReqDTO();
        operateBotReqDTO.setExchangeType(exchangeType);
        operateBotReqDTO.setDestinationCoin(destinationCoin);
        operateBotReqDTO.setSourceCoin(sourceCoin);
        operateBotReqDTO.setUserId(userId);

        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getMarketPriceDepth(exchangeOperateReqDTO);

        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()));
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

    @Override
    public JSONObject getCandleStick(Integer exchangeType, String userId, String destinationCoin, String sourceCoin, CandlestickInterval interval, Long startTime, Long endTime, int limit) throws Exception {
        ExchangeOperateReqDTO exchangeOperateReqDTO = new ExchangeOperateReqDTO();
        OperateBotReqDTO operateBotReqDTO = new OperateBotReqDTO();
        operateBotReqDTO.setExchangeType(exchangeType);
        operateBotReqDTO.setDestinationCoin(destinationCoin);
        operateBotReqDTO.setSourceCoin(sourceCoin);
        operateBotReqDTO.setUserId(userId);

        CandleStickVO candleStickVO = new CandleStickVO();
        candleStickVO.setInterval(interval);
        candleStickVO.setStartTime(startTime);
        candleStickVO.setEndTime(endTime);
        candleStickVO.setLimit(limit);

        exchangeOperateReqDTO.setOperateBotReqDTO(operateBotReqDTO);
        exchangeOperateReqDTO.setCandleStickVO(candleStickVO);

        ResponseVO responseVO = exchangeOperateServiceFeignApi.getCandleStick(exchangeOperateReqDTO);

        if (responseVO.getCode().equals(ResponseVO.SUCCESS)) {
            return JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()));
        } else {
            throw JSONObject.parseObject(JSONObject.toJSONString((LinkedHashMap) responseVO.getData()), Exception.class);
        }
    }

}
